/*
* Copyright (c) 2007 by Kirill Kolodyazhniy.
* See the file "license.terms" for information on usage and redistribution.
*/

#ifndef M_FILESYSTEM_H
#define M_FILESYSTEM_H

#include "archive.h"
#include "datastream.h"

#include <string>
#include <fstream>


namespace Engine
{
	/**
	*   Reads files from file system.
	*/
	class FileSystem: public Archive
	{
	public:
		/**
		*   Constructor.
		*   @param name folder name.
		*/
		FileSystem(const std::string& name);

		/**
		*   Destructor.
		*/
		~FileSystem(){}

		/**
		*   Open file for reading;
		*   @param name files name;
		*/
		virtual RefPtr<DataStream> ReadFile(const std::string& name)const;

		/** Find all file or directory names matching a given pattern in this archive.
		*   @param pattern The pattern to search for; wildcards (*) are allowed
		*   @param recursive Whether all paths of the archive are searched (if the archive has a concept of that)
		*   @param dirs Set to true if you want the directories to be listed instead of files
		*   @returns A list of filenames matching the criteria, all are fully qualified
		*/
		virtual VectorStringPtr Find(const std::string& pattern, bool recursive, bool dirs)const;

	private:

		void FindFiles(const std::string& pattern, bool recursive, bool dirs, VectorStringPtr simpleList)const;

	private:

		std::string m_name;///< Folder name.
	};


	/**
	*   Factory for creating objects for reading files from filesystem.
	*/
	class FileSystemFactory: public ArchiveFactory
	{
	public:

		FileSystemFactory():m_type("FileSystem"){}

		/**
		*   Returns the factory type.
		*/
		virtual const std::string& GetType() const {return m_type;}

		/**
		*   Creates a new object.
		*   @param name Name of the object to create
		*   @return	An object created by the factory. The type of the object depends on	the factory.
		*/
		virtual FileSystem* CreateInstance( const std::string& name );

	private:

		std::string m_type;
	};

	/**
	*   Reads files from file system.
	*/
	class FileSystemDataStream: public DataStream
	{
	public:

		/**
		*   Constructor.
		*/
		FileSystemDataStream(RefPtr<std::ifstream> s, size_t size);

		/**
		*   Destructor.
		*/
		~FileSystemDataStream();

		/**
		*   Read the requisite number of bytes from the stream, stopping at the end of the file.
		*   @param buf Reference to a buffer pointer
		*   @param count Number of bytes to read
		*   @returns The number of bytes read
		*/
		virtual size_t Read(void* buf, size_t count);

		/**
		*   Repositions the read point to a specified byte.
		*/
		virtual void Seek( size_t pos );

		/**
		*   Returns the current byte offset from beginning.
		*/
		virtual size_t Tell(void) const;

		/**
		*   Returns true if the stream has reached the end.
		*/
		virtual bool Eof(void) const;

		/**
		*   Close the stream, this makes further operations invalid.
		*/
		virtual void Close(void);

		/**
		*   Return stream size in bytes.
		*/
		virtual size_t GetSize();

	private:

		mutable RefPtr<std::ifstream> m_file;
		size_t                        m_size;
	};
}

#endif
